package com.xyh.transaction.service.imp;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xyh.transaction.common.ImageType;
import com.xyh.transaction.entity.Category;
import com.xyh.transaction.entity.Goods;
import com.xyh.transaction.entity.Image;
import com.xyh.transaction.entity.dto.category.CategoryDto;
import com.xyh.transaction.entity.dto.category.CategoryGoodsDto;
import com.xyh.transaction.entity.dto.user.ArrDto;
import com.xyh.transaction.entity.vo.CategorySubVo;
import com.xyh.transaction.entity.vo.CategoryVo;
import com.xyh.transaction.entity.vo.GoodsVo;
import com.xyh.transaction.exception.BusinessException;
import com.xyh.transaction.listener.MapCategoryImageEvent;
import com.xyh.transaction.listener.MapGoodsImageEvent;
import com.xyh.transaction.mapper.CategoryMapper;
import com.xyh.transaction.mapper.GoodsMapper;
import com.xyh.transaction.mapper.ImageMapper;
import com.xyh.transaction.service.CategoryService;
import com.xyh.transaction.utils.ImageUtils;
import com.xyh.transaction.utils.MappingUtil;
import com.xyh.transaction.utils.PageUtil;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CategoryServiceImpl implements CategoryService {

    @Resource
    private CategoryMapper categoryMapper;

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private ImageMapper imageMapper;

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    @Override
    public CategoryVo getCategoryVo(String id) {

        Category category = new Category();
        category.setId(Integer.parseInt(id));
        category.setParentId(Integer.parseInt(id));
        return getCategoryVoList(category).get(0);
    }

    @Override
    public List<CategoryVo> getHeadCategoryList() {

        return getCategoryVoList(new Category());
    }

    @Override
    public CategorySubVo getCategorySub(Integer id) {

        Category categorySub = categoryMapper.findById(id);
        CategorySubVo categorySubVo = MappingUtil.mapObject(categorySub, CategorySubVo.class);

        Category parentCate = categoryMapper.findById(categorySubVo.getParentId());
        categorySubVo.setParentName(parentCate.getName());
        categorySubVo.setGoods(new ArrayList<>());
        categorySubVo.setCategories(new ArrayList<>());
        categorySubVo.setBrands(new ArrayList<>());
        categorySubVo.setSaleProperties(new ArrayList<>());

        Goods goods = new Goods();
        goods.setCategoryId(id);
        List<GoodsVo> goodsVoList = goodsMapper.findAll(goods).stream().map(goods1 -> {
            GoodsVo goodsVo = MappingUtil.mapObject(goods1, GoodsVo.class);
            eventPublisher.publishEvent(new MapGoodsImageEvent(goods1,goodsVo));
            return goodsVo;
        }).collect(Collectors.toList());
        categorySubVo.getGoods().addAll(goodsVoList);
        return categorySubVo;
    }

    @Override
    public PageInfo<GoodsVo> getGoodsList(CategoryGoodsDto categoryGoodsDto) {

        Goods goods = new Goods();
        goods.setCategoryId(categoryGoodsDto.getCategoryId());

        Integer pageNum = categoryGoodsDto.getPageNum();
        Integer pageSize = categoryGoodsDto.getPageSize();

        pageNum = pageNum == null || pageNum <= 0 ? 1 : pageNum;
        pageSize = pageSize == null || pageSize <= 0 ? 10: pageSize; // 默认显示10条

        PageHelper.startPage(pageNum, pageSize);

        List<Goods> goodsList = goodsMapper.findAll(goods);

        PageInfo pageInfo = new PageInfo(goodsList);

        pageInfo.setList(goodsList.stream().map(goods1 -> {
            GoodsVo goodsVo = MappingUtil.mapObject(goods1, GoodsVo.class);
            eventPublisher.publishEvent(new MapGoodsImageEvent(goods1,goodsVo));
            return goodsVo;
        }).collect(Collectors.toList()));

        return pageInfo;
    }



    @Override
    public void updateCategory(CategoryDto categoryDto) {
        Category category = MappingUtil.mapObject(categoryDto, Category.class);
        if (StringUtils.isNotBlank(categoryDto.getParentName())) {
            Category cate = categoryMapper.findByName(categoryDto.getParentName());
            category.setParentId(cate.getId());
        }
        // 删除图片
        imageMapper.deleteByRelatedId(category.getId(), ImageType.CATEGORY);
        // 保存图片
        mappingCategoryImage(categoryDto.getPicture(), category.getName(), category.getId());
        categoryMapper.update(category);
    }

    @Override
    public void addCategory(CategoryDto categoryDto) {
        Category category = MappingUtil.mapObject(categoryDto, Category.class);
        Category cate = categoryMapper.findByName(categoryDto.getParentName());
        category.setParentId(cate.getId());
        int categoryId = categoryMapper.insert(category);
        // 保存图片
        mappingCategoryImage(categoryDto.getPicture(), category.getName(), categoryId);
    }

    private void mappingCategoryImage(String url, String categoryName, Integer categoryId) {
        // 把图片保存进t_image
        Image image = new Image();
        image.setAltText(categoryName);
        image.setUrl(ImageUtils.getFileNameFromUrl(url));
        image.setRelatedId(categoryId);
        image.setImageType(ImageType.CATEGORY);
        image.setCreateTime(LocalDateTime.now());
        image.setUpdateTime(LocalDateTime.now());
        imageMapper.insert(image);
    }

    @Override
    public void deleteCategory(ArrDto arrDto) {
        // 检查是否选择了分类
        if (arrDto.getId() == null || arrDto.getId().length == 0){
            throw new BusinessException("请选择要删除的分类");
        }
        // 检查产品大类下是否存在商品
        if (goodsMapper.findAllByCategoryIds(Arrays.asList(arrDto.getId())) != null) {
            throw new BusinessException("该分类下存在商品，不能删除");
        }
        // 删除图片
        Arrays.stream(arrDto.getId()).forEach(id -> {
            imageMapper.deleteByRelatedId(id, ImageType.CATEGORY);
        });

        categoryMapper.delete(arrDto.getId());
    }

    @Override
    public PageInfo<CategoryVo> getCategoryList(CategoryDto categoryDto) {
        Category category = MappingUtil.mapObject(categoryDto, Category.class);
        Category cate = categoryMapper.findByName(category.getName());
        if (cate != null) {
            category.setParentId(cate.getId());
        }
        List<CategoryVo> categoryVoList = getCategoryVoList(category);
        return PageUtil.paginateList(categoryVoList, categoryDto.getPageNum(), categoryDto.getPageSize());

    }

    @Override
    public List<CategorySubVo> getSubList() {
        return categoryMapper.findAllCategorySub().stream()
                .map(category -> {
                    CategorySubVo categorySubVo = MappingUtil.mapObject(category, CategorySubVo.class);
                    eventPublisher.publishEvent(new MapCategoryImageEvent(category,categorySubVo));
                    return categorySubVo;
                })
                .collect(Collectors.toList());
    }

    @NotNull
    private List<CategoryVo> getCategoryVoList(Category category) {
        List<Category> categoryList = categoryMapper.findAll(category);

        Map<Integer, List<CategoryVo>> parentIdMap = categoryList.stream()
                .filter(cate -> cate.getParentId() != null)
                .map(cate -> {
                    CategoryVo categoryVo = MappingUtil.mapObject(cate, CategoryVo.class);
                    eventPublisher.publishEvent(new MapCategoryImageEvent(cate,categoryVo));
                    Goods goods = new Goods();
                    goods.setCategoryId(cate.getId());
                    List<GoodsVo> goodsVos = goodsMapper.findAll(goods).stream().map(g -> {
                        GoodsVo goodsVo = MappingUtil.mapObject(g, GoodsVo.class);
                        eventPublisher.publishEvent(new MapGoodsImageEvent(g,goodsVo));
                        return goodsVo;
                    }).limit(4).collect(Collectors.toList());
                    categoryVo.setGoods(goodsVos);
                    return categoryVo;
                })
                .collect(Collectors.groupingBy(CategoryVo::getParentId));

        List<CategoryVo> categoryVoList = categoryList.stream()
                .filter(cate -> cate.getParentId() == null)
                .map(cate -> {
                    CategoryVo categoryVo = MappingUtil.mapObject(cate, CategoryVo.class);
                    eventPublisher.publishEvent(new MapCategoryImageEvent(cate,categoryVo));
                    Category ca = new Category();
                    ca.setParentId(cate.getId());
                    List<Integer> categoryIds = categoryMapper.findAll(ca).stream()
                            .map(Category::getId).collect(Collectors.toList());
                    List<Goods> goodsList = goodsMapper.findAllByCategoryIds(categoryIds);
                    List<GoodsVo> goodsVos = goodsList.stream().map(g -> {
                        GoodsVo goodsVo = MappingUtil.mapObject(g, GoodsVo.class);
                        eventPublisher.publishEvent(new MapGoodsImageEvent(g,goodsVo));
//                        List<Image> images = imageMapper.findByRelatedId(g.getId());
//                        if (images.isEmpty()){
//                            goodsVo.setPicture(Constant.DEFAULT_GOODS);
//                            goodsVo.setPictures(Constant.DEFAULT_GOODS_LIST.stream().map(url -> {
//                                ImageVo imageVo = new ImageVo();
//                                imageVo.setUrl(url);
//                                imageVo.setName("default image");
//                                return imageVo;
//                            }).collect(Collectors.toList()));
//                        }else {
//                            goodsVo.setPicture(images.get(0).getUrl());
//                            goodsVo.setPictures(images.stream().map(image -> {
//                                ImageVo imageVo = new ImageVo();
//                                imageVo.setName(image.getAltText());
//                                imageVo.setUrl(image.getUrl());
//                                return imageVo;
//                            }).collect(Collectors.toList()));
//                        }
                        return goodsVo;
                    }).limit(8).collect(Collectors.toList());
                    categoryVo.setGoods(goodsVos);
                    return categoryVo;

                })
                .collect(Collectors.toList());

        categoryVoList.forEach(categoryVo -> {
            List<CategoryVo> children = parentIdMap.get(categoryVo.getId()).stream()
                    .peek(ch -> ch.setParentName(categoryVo.getName()))
                    .collect(Collectors.toList());
            categoryVo.setChildren(children);
        });
        return categoryVoList;
    }
}
